package com.asa.chart.work;

import java.awt.EventQueue;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.asa.chart.FuShuMain;
import com.asa.chart.Transform2D;
import com.asa.chart.Transform3D22D;
import com.asa.chart.base.Line;
import com.asa.chart.base.Point;
import com.asa.fushu.MathUtilsFuShu;
import com.asa.fushu.RFunction;
import com.asa.fushu.bean.Fushu;

/**
 * 封装mvc
 * 
 * @author Administrator
 *
 */
public class AlgoVisualizer {

	private AlgoFrame frame;

	public static Calendar c;
	private long startTime;
	public static long midTime;
	

	private boolean show2DAxles = true;

	private List<String> textzhi;
	private List<double[]> textpointzhi;

	private List<List<double[][]>> zhiList;
	
	private int tupianN;
	private int dataArange;
	
	
	
	public AlgoVisualizer(final int sceneWidth, final int sceneHeight, int N, List<double[][]> zhi, int zoom,
			boolean show2DAxles) {
		super();
		this.show2DAxles = show2DAxles;
		List<List<double[][]>> zhiList = new ArrayList<>();
		zhiList.add(zhi);
		this.zhiList = zhiList;
		init(sceneWidth, sceneHeight, N, zhiList, zoom,null,null);
		c = Calendar.getInstance();
		startTime = c.getTimeInMillis();
		EventQueue.invokeLater(new Runnable() {// 用java事件分发（开了个线程）的方法来创建对话框

			public void run() {
				// TODO Auto-generated method stub
				frame = new AlgoFrame("wellcome", sceneWidth, sceneHeight);
				frame.addKeyListener(new AlgoKeyListener());
				frame.addMouseListener(new AlgoMouseListener());
				new Thread(new Runnable() {

					public void run() {
						// TODO Auto-generated method stub
						runmiage();
					}

				}).start();
				;

			}
		});

	}

	
	
	public AlgoVisualizer(final int sceneWidth, final int sceneHeight, int N, List<double[][]> zhi, int zoom,
			List<String> textzhi,List<double[]> textpointzhi) {
		super();
		List<List<double[][]>> zhiList = new ArrayList<>();
		zhiList.add(zhi);
		this.zhiList = zhiList;

		init(sceneWidth, sceneHeight, N, zhiList, zoom,textzhi,textpointzhi);
		c = Calendar.getInstance();
		startTime = c.getTimeInMillis();

		EventQueue.invokeLater(new Runnable() {// 用java事件分发（开了个线程）的方法来创建对话框

			public void run() {
				// TODO Auto-generated method stub
				frame = new AlgoFrame("wellcome", sceneWidth, sceneHeight);
				frame.addKeyListener(new AlgoKeyListener());
				frame.addMouseListener(new AlgoMouseListener());
				new Thread(new Runnable() {

					public void run() {
						// TODO Auto-generated method stub
						runmiage();
					}

				}).start();
				;

			}
		});

	}

	
	
	public AlgoVisualizer(final int sceneWidth, final int sceneHeight, int N, List<double[][]> zhi, int zoom) {
		super();
		List<List<double[][]>> zhiList = new ArrayList<>();
		zhiList.add(zhi);
		this.zhiList = zhiList;

		init(sceneWidth, sceneHeight, N, zhiList, zoom,null,null);
		c = Calendar.getInstance();
		startTime = c.getTimeInMillis();

		EventQueue.invokeLater(new Runnable() {// 用java事件分发（开了个线程）的方法来创建对话框

			public void run() {
				// TODO Auto-generated method stub
				frame = new AlgoFrame("wellcome", sceneWidth, sceneHeight);
				frame.addKeyListener(new AlgoKeyListener());
				frame.addMouseListener(new AlgoMouseListener());
				new Thread(new Runnable() {

					public void run() {
						// TODO Auto-generated method stub
						runmiage();
					}

				}).start();
				;

			}
		});

	}

	public AlgoVisualizer(final int sceneWidth, final int sceneHeight, int N, int zoom, List<List<double[][]>> zhiList) {
		// TODO Auto-generated constructor stub
		this.zhiList = zhiList;

		init(sceneWidth, sceneHeight, N, zhiList, zoom,null,null);
		c = Calendar.getInstance();
		startTime = c.getTimeInMillis();

		
		
		
		
		
		
		
		EventQueue.invokeLater(new Runnable() {// 用java事件分发（开了个线程）的方法来创建对话框

			public void run() {
				// TODO Auto-generated method stub
				frame = new AlgoFrame("wellcome", sceneWidth, sceneHeight);
				frame.addKeyListener(new AlgoKeyListener());
				frame.addMouseListener(new AlgoMouseListener());
				new Thread(new Runnable() {

					public void run() {
						// TODO Auto-generated method stub
						runmiage();
					}

				}).start();
				;

			}
		});
		
		
	}

	
	public AlgoVisualizer(final int sceneWidth, final int sceneHeight, int N, double zoom,int dataArange) {
		// TODO Auto-generated constructor stub
		init(sceneWidth, sceneHeight, N, zhiList, zoom,null,null);
		c = Calendar.getInstance();
		startTime = c.getTimeInMillis();
		this.dataArange = dataArange;
		EventQueue.invokeLater(new Runnable() {// 用java事件分发（开了个线程）的方法来创建对话框

			public void run() {
				// TODO Auto-generated method stub
				frame = new AlgoFrame("wellcome", sceneWidth, sceneHeight);
				frame.addKeyListener(new AlgoKeyListener());
				frame.addMouseListener(new AlgoMouseListener());
				new Thread(new Runnable() {

					public void run() {
						// TODO Auto-generated method stub
						runmiage();
					}

				}).start();
				;

			}
		});
	}


	List<RFunction> listRF;

	List<Line> mapline;
	List<List<Line>> canves;

	List<String> text;
	List<Point> textpoint;
	int sceneWidth;
	int sceneHeight;
	double zoom;

	
	
	
	
	
	
	
	
	
	
	public List<RFunction> getListRF() {
		return listRF;
	}



	public void setListRF(List<RFunction> listRF) {
		this.listRF = listRF;
	}



	private void init(final int sceneWidth, final int sceneHeight, int N, List<List<double[][]>> zhi123, double zoom,
			List<String> textzhi,List<double[]> textpointzhi) {

		this.sceneWidth = sceneWidth;
		this.sceneHeight = sceneHeight;
		this.zoom = zoom;
		
		mapline = new ArrayList<Line>();
		
		if (text==null) {
			this.text = new ArrayList<String>();
		}
		if (textpoint==null) {
			this.textpoint = new ArrayList<Point>();
		}
		
		
		
		if(textzhi!=null) {
			this.textzhi = textzhi;
		}else {
			this.textzhi = new ArrayList<String>();

		}
		if (textpointzhi!=null) {
			this.textpointzhi = textpointzhi;
		}else {
			this.textpointzhi = new ArrayList<double[]>();
		}
		

		initNumberAxis(sceneWidth, sceneHeight, zoom);
		
		if (textzhi!=null) {
			for (int i = 0; i < textzhi.size(); i++) {
				double[] pointzhi = textpointzhi.get(i);
				
				Point point = new Point();
				point.x = (int) (reverse_x(pointzhi[0] , zoom, sceneWidth));
				point.y = (int) (reverse_y(pointzhi[1] , zoom, sceneHeight));

				
//				spoint.x = (int) (reverse_x(x1 * zoom, sceneWidth));
//				spoint.y = (int) (reverse_y(y1 * zoom, sceneHeight));
//				epoint.x = (int) (reverse_x(x2 * zoom, sceneWidth));
//				epoint.y = (int) (reverse_y(y2 * zoom, sceneHeight));
				
				
				
				textpoint.add(point);
				text.add(textzhi.get(i));

			}
		}
		

	}

	/**
	 * 初始化数轴
	 * @param sceneWidth
	 * @param sceneHeight
	 * @param zhi
	 * @param zoom
	 */
	private void initNumberAxis(final int sceneWidth, final int sceneHeight, double zoom) {
		if (show2DAxles) {
			System.out.println(show2DAxles);
			// 画y轴
			{
				Point spoint = new Point();
				Point epoint = new Point();
				spoint.x = sceneWidth / 2;
				spoint.y = 0;
				epoint.x = sceneWidth / 2;
				epoint.y = sceneHeight;
				Line line = new Line();
				line.spoint = spoint;
				line.epoint = epoint;
				mapline.add(line);
			}

			// 画x轴
			{
				Point spoint = new Point();
				Point epoint = new Point();
				spoint.x = 0;
				spoint.y = sceneHeight / 2;
				epoint.x = sceneWidth;
				epoint.y = sceneHeight / 2;
				Line line = new Line();
				line.spoint = spoint;
				line.epoint = epoint;
				mapline.add(line);
			}

			// 画辅助线
			for (int i = 0; i <= sceneHeight / (zoom * 2); i++) {
				Point spoint = new Point();
				Point epoint = new Point();
				spoint.x = sceneWidth / 2 - 5;
				spoint.y = (int) (sceneHeight / 2 - i * zoom);
				epoint.x = sceneWidth / 2 + 5;
				epoint.y = (int) (sceneHeight / 2 - i * zoom);
				Line line = new Line();
				line.spoint = spoint;
				line.epoint = epoint;
				mapline.add(line);

				Point spoint2 = new Point();
				Point epoint2 = new Point();
				spoint2.x = sceneWidth / 2 - 5;
				spoint2.y = (int) (sceneHeight / 2 + i * zoom);
				epoint2.x = sceneWidth / 2 + 5;
				epoint2.y = (int) (sceneHeight / 2 + i * zoom);
				Line line2 = new Line();
				line2.spoint = spoint2;
				line2.epoint = epoint2;
				mapline.add(line2);

				text.add("" + i);
				textpoint.add(line.spoint);

				if (i == 0) {
					continue;
				}

				text.add("-" + i);
				textpoint.add(line2.spoint);
			}

			for (int i = 0; i <= sceneWidth / (zoom * 2); i++) {

				Point spoint = new Point();
				Point epoint = new Point();
				spoint.x = (int) (sceneWidth / 2 + i * zoom);
				spoint.y = sceneHeight / 2 - 5;
				epoint.x = (int) (sceneWidth / 2 + i * zoom);
				epoint.y = sceneHeight / 2 + 5;
				Line line = new Line();
				line.spoint = spoint;
				line.epoint = epoint;
				mapline.add(line);

				Point spoint2 = new Point();
				Point epoint2 = new Point();
				spoint2.x = (int) (sceneWidth / 2 - i * zoom);
				spoint2.y = sceneHeight / 2 - 5;
				epoint2.x = (int) (sceneWidth / 2 - i * zoom);
				epoint2.y = sceneHeight / 2 + 5;
				Line line2 = new Line();
				line2.spoint = spoint2;
				line2.epoint = epoint2;
				mapline.add(line2);

				text.add("" + i);
				textpoint.add(line.spoint);
				if (i == 0) {
					continue;
				}
				text.add("-" + i);
				textpoint.add(line2.spoint);

			}
		}		
		
		
	}



	private void initdata(final int sceneWidth, final int sceneHeight, List<List<double[][]>> zhiList, double zoom) {
		canves = new ArrayList<List<Line>>();

		
		List<double[][]> zhi = zhiList.get(tupianN%zhiList.size());
		
		
		for (int i = 0; i < zhi.size(); i++) {

			double[][] ds = zhi.get(i);
			List<Line> canve = new ArrayList<Line>();

			for (int j = 0; j < ds.length - 1; j++) {

				double x1 = ds[j][0];
				double y1 = ds[j][1];
				double x2 = ds[j + 1][0];
				double y2 = ds[j + 1][1];

				Point spoint = new Point();
				Point epoint = new Point();
				spoint.x = (int) (reverse_x(x1 , zoom, sceneWidth));
				spoint.y = (int) (reverse_y(y1 , zoom, sceneHeight));
				epoint.x = (int) (reverse_x(x2 , zoom, sceneWidth));
				epoint.y = (int) (reverse_y(y2 , zoom, sceneHeight));

//				spoint.x = (int) (x1*10);
//				spoint.y = (int) (y1*10);
//				epoint.x = (int) (x2*10);
//				epoint.y = (int) (y2*10);

				Line line = new Line();
				line.spoint = spoint;
				line.epoint = epoint;

				canve.add(line);

			}
			canves.add(canve);

		}
	}

	public double reverse_x(double x, double zoom, int w) {

		return x*zoom + w / 2;

	}

	public double reverse_y(double y, double zoom, int h) {
		return -y*zoom + h / 2;
	}

	private void runmiage() {
		while (true) {

			// 更新数据

//			System.out.println("刷新页面"+tupianN);
			if(zhiList!=null&&zhiList.size()>0) {
				initdata(sceneWidth, sceneHeight, zhiList, zoom);

			}
			
			if(listRF!=null&&listRF.size()>0) {
				canves = new ArrayList<List<Line>>();

				List<Fushu> y = MathUtilsFuShu.getY(-dataArange, dataArange, -dataArange, dataArange, 0.05, listRF.get(tupianN%listRF.size()));
				List<double[][]> zhi = new ArrayList<double[][]>();//函数的线簇
				for (int j = 0; j < y.size(); j++) {
					

					Fushu fushu = y.get(j);
//					System.out.println(fushu);
					List<double[][]> drawpoint_x3 = FuShuMain.fs2XY(fushu);
					zhi.addAll(drawpoint_x3);

				}
				for (int i = 0; i < zhi.size(); i++) {

					double[][] ds = zhi.get(i);
					List<Line> canve = new ArrayList<Line>();

					for (int j = 0; j < ds.length - 1; j++) {

						double x1 = ds[j][0];
						double y1 = ds[j][1];
						double x2 = ds[j + 1][0];
						double y2 = ds[j + 1][1];

						Point spoint = new Point();
						Point epoint = new Point();
						spoint.x = (int) (reverse_x(x1 , zoom, sceneWidth));
						spoint.y = (int) (reverse_y(y1 , zoom, sceneHeight));
						epoint.x = (int) (reverse_x(x2 , zoom, sceneWidth));
						epoint.y = (int) (reverse_y(y2 , zoom, sceneHeight));

//						spoint.x = (int) (x1*10);
//						spoint.y = (int) (y1*10);
//						epoint.x = (int) (x2*10);
//						epoint.y = (int) (y2*10);

						Line line = new Line();
						line.spoint = spoint;
						line.epoint = epoint;

						canve.add(line);

					}
					canves.add(canve);

				}
				
			}
			
			
			frame.render(mapline, canves, text, textpoint);

			c = Calendar.getInstance();
			
			if (isAnimated) {
				tupianN++;

			}
			AlgoVisHelper.pause(200);

		}
	}

	boolean isAnimated;

	private class AlgoKeyListener extends KeyAdapter {

		@Override
		public void keyReleased(KeyEvent event) {
			// TODO Auto-generated method stub
			super.keyReleased(event);
			if (event.getKeyCode() == KeyEvent.VK_SPACE) {
				isAnimated = !isAnimated;
			}else if (event.getKeyCode()==KeyEvent.VK_LEFT) {
				if(tupianN>0) {
					tupianN--;

				}

			}else if (event.getKeyCode()==KeyEvent.VK_RIGHT) {
				tupianN++;
			}
		}

	}

	private class AlgoMouseListener extends MouseAdapter {

		@Override
		public void mousePressed(MouseEvent event) {
			// TODO Auto-generated method stub

			event.translatePoint(0, -(frame.getBounds().height - frame.getCanvasHeight()));

			java.awt.Point point = event.getPoint();
			System.out.println(point);
			int x = point.x;
			int y = point.y;

			int index = x / 100;
			int indey = y / 100;

			System.out.println(index);
			System.out.println(indey);

		}

	}

}
